package ni;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * TCPSender_1 is used to send a file to a remoteUser. It is replacing the
 * TCPSender class that was managing the file proposal. Contrary to the
 * TCPSender class, this class is only connecting to a remote User and sending
 * the file.
 *
 * @author gb
 */
public class TCPSender_1 extends Thread {

    private String fileName;
    private File file;
    private String remoteUser;
    private Socket sock;
    private ChatNI ni;

    /**
     * Creates a TCPSender_1 object.
     *
     * @param ni needed to give feedback on the transfer
     * @param fileName needed to print a debug line and to give feedback
     * @param file needed to be sent
     * @param remoteUser needed to connect to the right person
     */
    public TCPSender_1(ChatNI ni, String fileName, File file, String remoteUser) {
        this.fileName = fileName;
        this.file = file;
        this.remoteUser = remoteUser;
        this.ni = ni;
    }

    /**
     * Connects to the remote user, Sends the file, Advises ni on the transfer,
     * Advises ni it is closing
     */
    @Override
    public void run() {
        ChatNI.printDebug("TCPSender", "run", "Connecting socket");
        try {
            this.sock = new Socket(ChatNI.extractIpFromUsername(this.remoteUser), ChatNI.receivePort);
        } catch (IOException ex) {
            System.err.println("In TCP_Sender : coul not access remote user " + this.remoteUser);
        }

        //Getting file length
        Path filepath = Paths.get(file.getAbsolutePath());
        long size = -1;
        try {
            size = Files.size(filepath);
        } catch (IOException ex) {
            System.err.println("In TCP_Sender : coul not get the size of the file");
        }

        //Getting output stream we will write on
        OutputStream os = null;
        try {
            os = this.sock.getOutputStream();
        } catch (IOException ex) {
            System.err.println("In TCP_Sender : coul not access socket output stream");
        }

        //===========================================
        //            SENDING FILE
        //===========================================       
        //Getting the input stream
        ChatNI.printDebug("TCPSender", "run", "File proposal accepted");
        if ((int) size != size) {
            System.err.println("In TCP_Sender : size is to big");
        }
        writeFileToOutputStream(file, (int) size, os);

        ChatNI.printDebug("TCPSender", "run", "Closing connection");

        try {
            this.sock.close();
        } catch (IOException ex) {
            System.err.println("In TCP_Sender : could not close socket");
        }

        //Transmission is done, let's advise NI it sent the file
        ni.processfileTransmission(fileName, remoteUser, Boolean.TRUE);

        //The thread's job is done, let's advise NI it is closing
        ni.processSenderThreadClosure(this);
    }

    /**
     * Reads a file and writes it inside a output stream
     *
     * @param file the file to write inside the output stream
     * @param size the size of the file
     * @param os the output stream in which the file will be written
     */
    private void writeFileToOutputStream(File file, int size, OutputStream os) {
        ChatNI.printDebug("TCPSender", "writeFileToOutputStream", "Creating the f.i.s on "
                + fileName);
        FileInputStream fis = null;

        try {
            fis = new FileInputStream(file);
        } catch (FileNotFoundException ex) {
            System.err.println("In TCP_Sender - writeFileToOutputStream : coul not create the file Input Stream");
        }
        byte[] fileData = new byte[size];
        try {
            fis.read(fileData);
            os.write(fileData);
            os.flush();
        } catch (IOException ex) {
            System.err.println("In TCP_Sender - writeFileToOutputStream : coul not read the fis");
        }

        /*
         try {
         synchronized (this) {
         Thread.currentThread().wait(10000);
         }
         } catch (InterruptedException ex) {
         System.err.println("In TCP_Sender - writeFileToOutputStream : coul not sleep 10 sec");
         }
         * */
        try {
            fis.close();
        } catch (IOException ex) {
            System.err.println("In TCP_Sender - writeFileToOutputStream : coul not close fis and bis");
        }
        ChatNI.printDebug("TCPSender", "writeFileToOutputStream", "File written");

    }

    /**
     * Close the socket after use
     */
    public void closeSockets() {
        try {
            this.sock.close();
        } catch (IOException ex) {
            System.err.println("In TCP_Receiver - readingInputIntoFile : could not close the connected Socket ");
        }
    }
}
